package fizzpicks.tetrapulp;

import fizzpicks.tetrapulp.tetrapulp.*;

import java.util.Set;

/**
 * Created by will
 * Date: May 4, 2008 2:25:55 AM
 */
public class LJTester {

    public static LJView[] views;
    public int nPlayers = 1;

    public static LJControl control;
    public static LJField field;
    public static LJView view;
    public static LJInput input;

    public void init() {
        control = new LJControl();
        field = new LJField();
        field.gimmick = LJGM.ATYPE;
        view = new LJView(null,control,field);
        input = new LJInput();
        Scenario.predefPresets[1].applyPreset(view);

        views = new LJView[1];
        views[0] = view;

    }

    public static void main(String[] args) {
        control = new LJControl();
        field = new LJField();
        field.gimmick = LJGM.ATYPE;
        view = new LJView(null,control,field);
        input = new LJInput();
        Scenario.predefPresets[1].applyPreset(view);

        views = new LJView[1];
        views[0] = view;
        LJTester tester = new LJTester();
        tester.play();
    }


    void play() {

        boolean canceled = false;

        for (int player = 0; player < nPlayers; ++player) {
            final LJField p = views[player].field;
            final LJControl ctl = views[player].control;

            ctl.countdown = 6;
            ctl.presses = 0;

            /* Load replay if needed */
        }
        for (int player = 0; player < nPlayers; ++player) {
            final LJField p = views[player].field;
            Lockjaw.newGame(p);
            Gimmicks.initGimmicks(p);
            views[player].nLockTimes = 0;
            views[player].hideNext = false;
            updField(views[player], new LJBits(true));
        }

//        startingAnimation(v[0]);
        for (int player = 0; player < nPlayers; ++player) {
            views[player].control.lastKeys = new LJBits(false);
            views[player].control.repressKeys = new LJBits(false);
            blitField(views[player]);
        }

//      int lastTime = getTime();

//        playFrame(canceled, lastTime);
        System.out.println("fieldstate="+ views[0].field.state);

    }

    public void playFrame(boolean canceled, int lastTime, LJInput in) {
//        while(views[0].field.state != LJState.GAMEOVER && !canceled) {
/*
          if (getTime() == lastTime) {
            Thread.yield();
          }
*/
  //        canceled |= ljHandleConsoleButtons(v[0]);
//          while (getTime() - lastTime > 0) {
            for (int player = 0; player < nPlayers; ++player) {
                lastTime = playFrameLogic(lastTime, player, in);
            }

/*
            ++lastTime;
          }
*/

          for (int player = 0; player < nPlayers; ++player) {
              drawField(lastTime, player);
          }
        }
//    }

    public int playFrameLogic(int lastTime, int player, LJInput in) {
        final LJField p = views[player].field;
        final LJControl ctl = views[player].control;
        int curTime = getTime();

        //            addKeysToInput(in, readPad(player), p, ctl);

        // when returning from pause, catch up the speed control
/*
        if (curTime - lastTime > 10
            || curTime - lastTime < -10) {
          lastTime = curTime;
        }
*/

        {
                boolean irsAttempted = (p.sounds.contains(LJSND.SPAWN) || p.sounds.contains(LJSND.HOLD))
                             && in.rotation != 0 && ctl.initialRotate != 0;

          // The next line does ALL the game logic.
          LJBits updatedRows = Lockjaw.frame(p, in).add(Gimmicks.gimmicks(p, ctl));

//            System.out.println("p.y = "+p.y);
          views[player].backDirty.add(updatedRows);
          if (irsAttempted && (p.sounds.contains(LJSND.ROTATE))) {
            p.sounds.add(LJSND.IRS);
          }
        }

        // items is a partly view-based gimmick
        if (p.gimmick == LJGM.ITEMS && (p.sounds.contains(LJSND.SPAWN))) {
          views[player].hideNext = (views[player].field.nPieces > 7);
          views[player].frontDirty.dirtyNext = true;
        }

        // five, four, three, two, one
        int curCountdown = ctl.countdown;
        if (p.gimmick == LJGM.ULTRA && p.gameTime >= 10500) {
          curCountdown = (int)(10859 - p.gameTime) / 60;
        } else if (p.gimmick == LJGM.BTYPE) {
          curCountdown = 40 - p.lines;
        } else if (p.gimmick == LJGM.BABY) {
          curCountdown = (309 - views[player].control.presses) / 10;
        } else if (p.gimmick == LJGM.DRILL && (p.sounds.contains(LJSND.LINE))) {
          int line = Lockjaw.bfffo(p.tempRows);
          if (line < curCountdown)
          curCountdown = line;
        }

        // we have to wait for the new piece to come out
        // so that the score is credited properly
        if (curCountdown <= 0
            && (p.state == LJState.NEW_PIECE
                || p.state == LJState.FALLING
                || p.state == LJState.LANDED)) {
          p.state = LJState.GAMEOVER;
        }

        playSoundEffects(views[player], p.sounds, curCountdown);
        ctl.countdown = curCountdown;

        // Update speedometer
        if (p.sounds.contains(LJSND.LOCK)) {
          for (int i = LJView.N_SPEED_METER_PIECES - 2; i >= 0; --i) {
            views[player].lockTime[i + 1] = views[player].lockTime[i];
          }
          views[player].lockTime[0] = (int)p.gameTime;
          if (views[player].nLockTimes < LJView.N_SPEED_METER_PIECES) {
            ++views[player].nLockTimes;
          }
          views[player].frontDirty.dirtyScore();
        }

        // If the piece was just spawned, move the trail to the piece's
        // starting position and redraw next pieces.
        if (p.sounds.contains(LJSND.SPAWN) || p.sounds.contains(LJSND.HOLD)) {
          views[player].trailY = p.y;
          views[player].frontDirty.dirtyNext();
        }
        return lastTime;
    }

    public void drawField(int lastTime, int player) {
        final LJField p = views[player].field;
        if (p.state == LJState.GAMEOVER && views[player].hidePF) {
          views[player].hidePF = false;
          views[player].backDirty.add((1 << Lockjaw.LJ_PF_VIS_HT) - 1);
        }

        updField(views[player], views[player].backDirty);
        views[player].frontDirty.add(views[player].backDirty);
        views[player].backDirty.clear();

        // If piece is falling or landed, and it wasn't just spawned,
        // draw the piece and its shadow.

        if (p.sounds.contains(LJSND.SPAWN) || p.sounds.contains(LJSND.HOLD)) {
          // piece was just spawned, so don't draw the piece
        }
        // Otherwise, if the piece is falling or landed, draw it.
        else if (p.state == LJState.FALLING || p.state == LJState.LANDED
                  || p.sounds.contains(LJSND.LOCK)) {
          if (views[player].hideShadow != LJSHADOW.NO_FALLING) {
            if (p.state == LJState.FALLING && views[player].hideShadow.isColored()) {
              drawShadow(views[player]);
            }
            drawFallingPiece(views[player]);
          }
        }

        ljBeginDraw(views[player], getTime() - lastTime < 2);
        drawScore(views[player]);
        blitField(views[player]);
        ljEndDraw(views[player]);
//        System.out.println("pstate="+p.state);
    }

    private void playSoundEffects(LJView ljView, Set<LJSND> sounds, int curCountdown) {
//        System.out.println("playSoundEffects curcountdown="+curCountdown+"sndlength="+sounds.size());
        for (LJSND snd : sounds) {
            System.out.println("snd=" + snd);
        }
    }

    private void ljEndDraw(LJView ljView) {
//        System.out.println("ljEndDraw");
    }

    private void blitField(LJView ljView) {
//        System.out.println("blitField");
    }

    private void drawScore(LJView ljView) {
//        System.out.println("drawScore");
    }

    private void drawFallingPiece(LJView ljView) {
//        System.out.println("drawFallingPiece");
    }

    private void ljBeginDraw(LJView ljView, boolean b) {
//        System.out.println("ljBeginDraw");
    }

    private void drawShadow(LJView ljView) {
//        System.out.println("drawShadow");
    }

    private void updField(LJView ljView, LJBits backDirty) {
//        System.out.println("updField");
    }

    private int getTime() {
        return (int)Math.abs(System.currentTimeMillis());
    }

}
